package com.xboard.server.dao.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.FilterOperator;
import com.xboard.server.common.exception.DataAccessException;
import com.xboard.server.dao.FxDao;
import com.xboard.server.manager.DataManager;

/**
 * Handles requests for the application home page.
 */
@Repository
public class FxDaoImpl implements FxDao{

	@Autowired
	private DataManager dataManager;
	
	// Order data
	private String FxOrder = "FxData";  // JDO table name
	private String Key_FxOrder = "symbol";
	
	// Close History
	private String FxHistory = "FxOrderHistory";
	private String Key_FxHistory = "ticket";

	// FX Chart data
	private String FxChart = "FxChart";
	private String Key_FxChart = "symbol";
	
	// Stop, start or open, close
	private String FxCmd = "FxCommand";
	private String Key_FxCmd = "symbol";

	// Account profit
	private String FxAccount = "FxAccount";
	private String Key_FxAccount = "account";
	
	public FxDaoImpl(){
		
	}
	
	@Override
	public void addFx(Map<String, Object> Fx){
		try {
		    Key fxKey = KeyFactory.createKey(FxOrder, UUID.randomUUID().toString());
	        
		    Date date = new Date();
		    Entity en = getEntity(FxOrder, Key_FxOrder, Fx.get(Key_FxOrder).toString());
		    if(en!=null && en.hasProperty(Key_FxOrder)){
		    	updateFx(Fx);
		    }else{
		        Entity enty = new Entity(FxOrder, fxKey);			
				enty.setProperty("symbol", Fx.get("symbol"));
				enty.setProperty("trend", Fx.get("trend"));
				enty.setProperty("signalValue", Fx.get("signalValue"));
				enty.setProperty("nowValue", Fx.get("nowValue"));
				enty.setProperty("profit", Fx.get("profit"));
				enty.setProperty("date", date);
				dataManager.insert(enty);
		    }
			System.out.println("add/"+Fx.get("symbol")+"/"+Fx.get("trend")+"/"+Fx.get("signalValue")+"/"+Fx.get("nowValue")+"/"+Fx.get("profit"));
			
		} catch (Exception e) {
			throw new DataAccessException(e);
		}
	}
	@Override
	public void addTicket(Map<String, Object> Fx){
		try {
		    Key fxKey = KeyFactory.createKey(FxHistory, UUID.randomUUID().toString());

		    Date date = new Date();
		    Entity en = getEntity(FxHistory, Key_FxHistory, Fx.get(Key_FxHistory).toString());
		    if(en!=null && en.hasProperty(Key_FxHistory)){
		    	updateTicket(Fx);
		    }else{
		        Entity enty = new Entity(FxHistory, fxKey);			
				enty.setProperty("symbol", Fx.get("symbol"));
				enty.setProperty("trend", Fx.get("trend"));
				enty.setProperty("ticket", Fx.get("ticket"));
				enty.setProperty("lots", Fx.get("lots"));
				enty.setProperty("price", Fx.get("price"));
				enty.setProperty("profit", Fx.get("profit"));
				enty.setProperty("date", date);
				dataManager.insert(enty);
		    }
			System.out.println("addHistoy/"+Fx.get("symbol")+"/"+Fx.get("trend")+"/"+Fx.get("ticket")+"/"+Fx.get("lots")+"/"+Fx.get("price")+"/"+Fx.get("profit"));
			
		} catch (Exception e) {
			throw new DataAccessException(e);
		}
	}
	@Override
	public void addChart(Map<String, Object> Fx){
		try {
		    Key fxKey = KeyFactory.createKey(FxChart, UUID.randomUUID().toString());
		    Date date = new Date();
		    
		    Entity enty = new Entity(FxChart, fxKey);			
		    enty.setProperty("price", Fx.get("price"));
		    enty.setProperty("symbol", Fx.get("symbol"));
			enty.setProperty("date", date);
			dataManager.insert(enty);
			delChart((String)Fx.get("symbol")); // 최근 300개 남기고 모두 삭제
			System.out.println("addChart/"+Fx.get("symbol")+"/"+Fx.get("price"));
			
		} catch (Exception e) {
			throw new DataAccessException(e);
		}
	}
	@Override
	public void addCmd(Map<String, Object> Fx){
		try {
		    Date date = new Date();
		    System.out.println("check data :  "+ FxCmd + " / "+ Key_FxCmd + " / "+ Fx.get(Key_FxCmd).toString() );
		    Entity en = getEntity(FxCmd, Key_FxCmd, Fx.get(Key_FxCmd).toString());
		    
		    if(en!=null && en.hasProperty(Key_FxCmd)){
		    	System.out.println("updateCmd "+ en.getProperty("symbol"));
		    	updateCmd(Fx);
		    }else{
		    	System.out.println("insertCmd" + Fx.get("symbol"));
		    	Entity enty = new Entity(FxCmd, Fx.get("symbol").toString());			
		    	enty.setProperty("symbol", Fx.get("symbol"));
		    	enty.setProperty("command", Fx.get("command"));
			    enty.setProperty("isopen", Fx.get("isopen"));
				enty.setProperty("date", date);
				dataManager.insert(enty);
		    }
			
			System.out.println("addCmd/"+Fx.get("symbol")+"/"+Fx.get("command")+"/"+Fx.get("isopen"));
			
		} catch (Exception e) {
			throw new DataAccessException(e);
		}
	}
	@Override
	public void addAccount(Map<String, Object> Fx){
		try {
		    Key fxKey = KeyFactory.createKey(FxAccount, UUID.randomUUID().toString());
	        
		    Date date = new Date();
		    Entity en = getEntity(FxAccount, Key_FxAccount, Fx.get(Key_FxAccount).toString());
		    if(en!=null && en.hasProperty(Key_FxAccount)){
		    	updateAccount(Fx);
		    }else{
		        Entity enty = new Entity(FxAccount, fxKey);			
				enty.setProperty("account", Fx.get("account"));
				enty.setProperty("lots", Fx.get("lots"));
				enty.setProperty("profit", Fx.get("profit"));
				enty.setProperty("opencount", Fx.get("opencount"));
				enty.setProperty("date", date);
				dataManager.insert(enty);
		    }
			System.out.println("addAccount/"+Fx.get("account")+"/"+Fx.get("lots")+"/"+Fx.get("profit")+"/"+Fx.get("opencount"));
			
		} catch (Exception e) {
			throw new DataAccessException(e);
		}
	}	
	@Override
	public List<Map<String,Object>> listFx(){
		List<Map<String,Object>> list= new ArrayList<Map<String,Object>>();
		Query query = new Query(FxOrder).addSort("symbol", Query.SortDirection.DESCENDING);

		try {
			list = dataManager.list(query);

		} catch (Exception e) {
			throw new DataAccessException(e);
		}
		return list;
	}
	@Override
	public List<Map<String,Object>> listHistory(){
		List<Map<String,Object>> list= new ArrayList<Map<String,Object>>();
		Query query = new Query(FxHistory).addSort("date", Query.SortDirection.DESCENDING);
		
		try {
			list = dataManager.list(query);

		} catch (Exception e) {
			throw new DataAccessException(e);
		}
		return list;
	}
	@Override
	public List<Map<String,Object>> listHistory(String symbol){
		List<Map<String,Object>> list= new ArrayList<Map<String,Object>>();
		Query query = new Query(FxHistory);
		query.addFilter("symbol", FilterOperator.EQUAL, symbol);
		query.addSort("date", Query.SortDirection.DESCENDING);
		
		try {
			list = dataManager.list(query);

		} catch (Exception e) {
			throw new DataAccessException(e);
		}
		return list;
	}	
	@Override
	public List<Map<String,Object>> listAccount(){
		List<Map<String,Object>> list= new ArrayList<Map<String,Object>>();
		Query query = new Query(FxAccount);
		try {
			list = dataManager.list(query);

		} catch (Exception e) {
			throw new DataAccessException(e);
		}
		return list;
	}	
	@Override
	public List<Map<String,Object>> chart(String symbol){
		List<Map<String,Object>> list= new ArrayList<Map<String,Object>>();
		Query query = new Query(FxChart);
		query.addFilter("symbol", FilterOperator.EQUAL, symbol);
		query.addSort("date", Query.SortDirection.ASCENDING);

		try {
			list = dataManager.list(query);

		} catch (Exception e) {
			throw new DataAccessException(e);
		}
		return list;
	}	
	@Override
	public Map<String,Object> getFx(String symbol){
		Map<String,Object> data = new HashMap<String,Object>();
		try {
			
			Entity enty = getEntity(FxOrder,Key_FxOrder,symbol);
			
			data.put("symbol", enty.getProperty("symbol"));
			data.put("trend", enty.getProperty("trend"));
			data.put("signalValue", enty.getProperty("signalValue"));
			data.put("nowValue", enty.getProperty("nowValue"));
			data.put("profit", enty.getProperty("profit"));
			data.put("date", enty.getProperty("date"));
			
		} catch (Exception e) {
			throw new DataAccessException(e);
		}
		return data;
	}	
	@Override
	public Map<String,Object> getCmd(String symbol){
		Map<String,Object> data = new HashMap<String,Object>();
		try {
			
			Entity enty = getEntity(FxCmd,Key_FxCmd,symbol);
			data.put("symbol", enty.getProperty("symbol"));
			data.put("command", enty.getProperty("command"));
			data.put("isopen", enty.getProperty("isopen"));
			data.put("date", enty.getProperty("date"));
			System.out.println();
		} catch (Exception e) {
			throw new DataAccessException(e);
		}
		return data;
	}	
	@Override
	public void updateFx(Map<String, Object> Fx){
		try {
			String symbol = Fx.get(Key_FxOrder).toString();
			Date date = new Date();
			
			Entity enty = getEntity(FxOrder,Key_FxOrder,symbol);			

			enty.setProperty("trend", Fx.get("trend"));
			enty.setProperty("signalValue", Fx.get("signalValue"));
			enty.setProperty("nowValue", Fx.get("nowValue"));
			enty.setProperty("profit", Fx.get("profit"));
			enty.setProperty("date", date);
						
			dataManager.update(enty);	
		} catch (Exception e) {
			throw new DataAccessException(e);
		}
	}
	@Override
	public void updateTicket(Map<String, Object> Fx){
		try {

			String ticket = Fx.get(Key_FxHistory).toString();
			Date date = new Date();
			
			Entity enty = getEntity(FxHistory,Key_FxHistory,ticket);			
			enty.setProperty("symbol", Fx.get("symbol"));
			enty.setProperty("trend", Fx.get("trend"));
			enty.setProperty("ticket", Fx.get("ticket"));
			enty.setProperty("lots", Fx.get("lots"));
			enty.setProperty("price", Fx.get("price"));
			enty.setProperty("profit", Fx.get("profit"));
			enty.setProperty("date", date);
						
			dataManager.update(enty);	
		} catch (Exception e) {
			throw new DataAccessException(e);
		}
	}	
	@Override
	public void updateCmd(Map<String, Object> Fx){
		try {

			String symbol = Fx.get(Key_FxCmd).toString();
			Date date = new Date();
			
			Entity enty = getEntity(FxCmd,Key_FxCmd,symbol);			
			enty.setProperty("command", Fx.get("command"));
			enty.setProperty("isopen", Fx.get("isopen"));
			enty.setProperty("date", date);
						
			dataManager.update(enty);	
		} catch (Exception e) {
			throw new DataAccessException(e);
		}
	}		
	@Override
	public void updateAccount(Map<String, Object> Fx){
		try {
			String symbol = Fx.get(Key_FxAccount).toString();
			Date date = new Date();
			
			Entity enty = getEntity(FxAccount,Key_FxAccount,symbol);			

			enty.setProperty("account", Fx.get("account"));
			enty.setProperty("lots", Fx.get("lots"));
			enty.setProperty("profit", Fx.get("profit"));
			enty.setProperty("opencount", Fx.get("opencount"));
			enty.setProperty("date", date);
						
			dataManager.update(enty);	
		} catch (Exception e) {
			throw new DataAccessException(e);
		}
	}	
	@Override
	public void deleteFx(String symbol){
		try {
			dataManager.delete(getEntity(FxOrder,Key_FxOrder,symbol));	
		} catch (Exception e) {
			throw new DataAccessException(e);
		}
	}
	@Override
	public void delChart(String symbol){
		try {
			Query query = new Query(FxChart);
			query.addFilter("symbol", FilterOperator.EQUAL, symbol);
			query.addSort("date", Query.SortDirection.DESCENDING);
			
			dataManager.deleteChart(query);	
		} catch (Exception e) {
			throw new DataAccessException(e);
		}
	}
	@Override
	public void deleteCmd(String symbol){
		try {
			Query query = new Query(FxCmd);
			query.addFilter("symbol", FilterOperator.EQUAL, symbol);
			query.addSort("date", Query.SortDirection.DESCENDING);
			
			dataManager.deleteAll(query);	
		} catch (Exception e) {
			throw new DataAccessException(e);
		}
	}	
	
	@Override
	public void deleteFx(String table, String name, String value){
		try {
			dataManager.delete(getEntity(table,name,value));	
		} catch (Exception e) {
			throw new DataAccessException(e);
		}
	}

	@Override
	public Key getKey(String table, String name, String value){
		Key key = null;
		try {
	        Query query = new Query(table);
			query.addFilter(name, FilterOperator.EQUAL, value);
			
			key = dataManager.getKey(query);
			
		} catch (Exception e) {
			throw new DataAccessException(e);
		}
		return key;
	}	
	@Override
	public Entity getEntity(String table, String name, String value){
		Entity enFx = null;
		try {
	        Query query = new Query(table);
			query.addFilter(name, FilterOperator.EQUAL, value);
			enFx = dataManager.getEntity(query);
			
		} catch (Exception e) {
			throw new DataAccessException(e);
		}
		return enFx;
	}	
		
}
